
/**
 * AppleIIGo
 * 2IMG Disk Image class
 * (C) 2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#include <string.h>
#include "TwoImgDiskImage.h"

bool TwoImgDiskImage::readHeader(FILE * diskImageFile,
								 UINT32 * diskImageOffset,
								 UINT32 * diskImageByteNum,
								 char ** diskImageExtension,
								 UINT8 * gcrVolume,
								 bool * isWriteProtectionForced) {
	TwoImgHeaderType twoImgHeader;
	if (fread(&twoImgHeader, sizeof(twoImgHeader), 1, diskImageFile) != 1)
		return false;
	
	if (strncmp(twoImgHeader.id, "2IMG", 4))
		return false;
	
	if (getLittleEndianUINT16(&twoImgHeader.headerByteNum) <
		sizeof(twoImgHeader))
		return false;
	
	if (getLittleEndianUINT16(&twoImgHeader.headerVersion) > TWOIMGVERSION)
		return false;
	
	UINT32 twoImgDiskImageOffset =
		getLittleEndianUINT32(&twoImgHeader.diskImageOffset);
	UINT32 twoImgDiskImageByteNum = 
		getLittleEndianUINT32(&twoImgHeader.diskImageByteNum);
	UINT32 twoImgDiskImageProdosBlockNum = 
		getLittleEndianUINT32(&twoImgHeader.prodosBlockNum);
	
	if ((twoImgDiskImageOffset + twoImgDiskImageByteNum) > *diskImageByteNum)
		return false;
	
	switch (getLittleEndianUINT32(&twoImgHeader.diskImageFormat)) {
		case TWOIMGFORMAT_GCR62_DOS:
			*diskImageExtension = "dsk";
			break;
		case TWOIMGFORMAT_GCR62_PRODOS:
			*diskImageExtension = "hdv";
			break;
		case TWOIMGFORMAT_NIB:
			*diskImageExtension = "nib";
			break;
		default:
			return false;
	}
	
	*diskImageOffset = twoImgDiskImageOffset;
	*diskImageByteNum = (twoImgDiskImageByteNum ? twoImgDiskImageByteNum :
						 twoImgDiskImageProdosBlockNum * 512);
	
	UINT32 twoImgFlags = getLittleEndianUINT32(&twoImgHeader.flags);
	
	if (getBit(twoImgFlags, TWOIMGFLAGS_VOLUME))
		*gcrVolume = twoImgFlags & 0xff;
	*isWriteProtectionForced =	getBit(twoImgFlags, TWOIMGFLAGS_WRITEPROTECTED);
	
	return true;
}

bool TwoImgDiskImage::isDiskImageValid(char * diskImagePath,
									   UINT32 * diskImageOffset,
									   UINT32 * diskImageByteNum,
									   char ** diskImageExtension,
									   UINT8 * diskVolume,
									   bool * isWriteProtectionForced) {
	FILE * diskImageFile;
	bool isError = false;
	
	*diskImageExtension = NULL;
	
	if (!(diskImageFile = fopen(diskImagePath, "rb")))
		return false;
	
	isError = !readHeader(diskImageFile,
						  diskImageOffset,
						  diskImageByteNum,
						  diskImageExtension,
						  diskVolume,
						  isWriteProtectionForced);
	
	fclose(diskImageFile);
	
	return !isError;
}
